iT邦幫忙

2023 iThome 鐵人賽

DAY 8
0
Mobile Development

SwiftUI 的大大小小系列 第 8

Day 8 - 在 SwiftUI 如何使用 safeAreaInset 建立貼於底部的 UI

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20230908/20140200WaRSRFDASc.png

前一篇第 7 天是提到「在 SwiftUI 如何實作多欄位 List - LazyVGrid 與 GridItem」,雖然本系列文章基本上沒有前後關聯,如果你是還沒讀過前一篇的讀者,也推薦你去讀讀。

Safe Area

Safe Area 是 Apple 為了解決 iPhone 有瀏海 (notch) 或後來的動態島、圓角螢幕等導致螢幕有部分不適合互動或顯示,而提出的畫面佈局機制。

所以在官方的建議在預設情形之下,畫面盡可能地在 Safe Area 內顯示。

例外

但是在不同情境下,我們仍然有需要和 Safe Area 打交道,這時候就可以用到 safeAreaInset 。例如這樣子的 UI :

https://ithelp.ithome.com.tw/upload/images/20230908/20140200SHcGfvWV6Q.png

  • 按鈕需要貼在 Safe Area 邊緣
  • 背景需要拓展到螢幕邊緣

初始程式碼

我們先做一個簡單的 List ,這個畫面用 Scroll View 顯示了一個清單,並包含了一些基本樣式和按鈕


struct ContentView: View {
    var body: some View {
        ScrollView {
            ForEach(0..<30, id:\.self) { episode in
                HStack(alignment:.center) {
                    Text("Day \(episode)")
                    Spacer()
                    buttons()
                }
                .padding(.vertical, 8)
                .padding(.horizontal)
            }
            .frame(maxWidth: .infinity)
        }
    }
    
    private func buttons() -> some View {
        HStack(spacing: 8) {
            Button {} label: {
                Image(systemName: "heart")
            }
            .foregroundColor(Color.pink)
            Button {} label: {
                Image(systemName: "bookmark")
            }
            .foregroundColor(Color.blue)
        }
    }
}

執行或在 Xcode 裡預覽後,畫面就會像這樣:

0802

加入 safeAreaInset

在初始的程式碼加上一段

.safeAreaInset(edge: .bottom) { /* ... */ }

就能夠在畫面的下半部加上自己想要的 UI ,並設定背景

0803

程式碼

struct ContentView: View {
    var body: some View {
        ScrollView {
            ForEach(0..<30, id:\.self) { episode in
                HStack(alignment:.center) {
                    Text("Day \(episode)")
                    Spacer()
                    buttons()
                }
                .padding(.vertical, 8)
                .padding(.horizontal)
            }
            .frame(maxWidth: .infinity)
        }
        // 從這裡
        .safeAreaInset(edge: .bottom) {
            HStack {
                Spacer()
                Button {} label: {
                    Text("鐵人發文")
                        .font(.system(size: 14, weight: .bold))
                        .padding()
                }
                .foregroundColor(.teal)
                .background(
                    RoundedRectangle(cornerRadius: 10)
                        .foregroundColor(.white)
                )
                .padding(.vertical)
                .padding(.horizontal, 24)
            }
            .frame(maxWidth: .infinity)
            .background(Color.teal)
        }
        // 到這裡
    }
    
    private func buttons() -> some View { /* 省略 */ }
}

更換 edge

在上面的程式碼我們把參數 edge 設定為 .bottom 。當然如果有需要也可以設為其他邊界,例如 .top ,就會很像一個 Navigation Bar 的效果了:

0804

結語

到這裡就是在 SwiftUI 該如何使用 safeAreaInset 。如果有疑問、回饋,歡迎留言討論~

那今天的 SwiftUI 的大大小小就到這邊,以上,明天見!

環境

  • Xcode 15 beta 8

本篇使用到的 UI 元件和 modifiers 基本上沒有受到版本更新影響,
因此 Xcode 14 等環境下使用也是沒問題的。


上一篇
Day 7 - 在 SwiftUI 如何實作多欄位 List - LazyVGrid 與 GridItem
下一篇
Day 9 - 在 SwiftUI 如何使用 ignoresSafeArea 達成全畫面效果
系列文
SwiftUI 的大大小小30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言